package com.dmagic.cms.common.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dmagic.cms.common.dao.CommonDao;
import com.dmagic.cms.common.entity.ModifyInfoEntity;
import com.dmagic.cms.common.exception.ServiceException;
import com.dmagic.cms.common.exception.ValidateException;
import com.dmagic.cms.common.util.PropertiesUtils;
import com.dmagic.cms.common.util.StringUtil;

@Service
public abstract class CommonService<T extends ModifyInfoEntity> {
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private CacheManager ehcacheManager;

    private static final String CACHE_NAME = "LocalCache";

    /**
     * rewrite for service partner business
     * 
     * @see com.crown.common.dao.SimpleHibernateDao#save(java.lang.Object)
     */
    public void saveEntity(T entity) throws ValidateException {
        getCommonDao().saveEntity(entity);
    }

    /**
     * getEntityById
     * 
     * @author Cy.zhong
     * @param id
     * @return T class
     */
    public T getEntityById(final Serializable id) {
        return getCommonDao().getEntityById(id);
    }

    /**
     * logical delete, update set isObsoleteDate = system date rewrite delete
     * entity for service partner business
     * 
     * @author songlin.li
     * @param entity
     */
    public void deleteEntity(final T entity) {
        getCommonDao().deleteEntity(entity);
    }

    /**
     * logical delete, update set isObsoleteDate = system date rewrite delete
     * entity for service partner business
     * 
     * @author songlin.li
     * @param id
     */
    public void deleteEntityById(final Serializable id) {
        getCommonDao().deleteEntityById(id);
    }

    /**
     * getEntityByIdForLog
     * 
     * @author Cy.zhong
     * @param id
     * @return
     */
    public T getEvictEntityById(final Serializable id) {
        return getCommonDao().getEvictEntityById(id);
    }

    /**
     * physically deleted
     * 
     * @author songlin.li
     * @param id
     */
    public void deleteById(final Serializable id) {
        getCommonDao().deleteById(id);
    }

    /**
     * physically deleted
     * 
     * @author songlin.li
     * @param entity
     */
    public void deleteByEntity(final T entity) {
        getCommonDao().deleteByEntity(entity);
    }

    /**
     * get an entity include physically deleted and logical delete
     * 
     * @author songlin.li
     * @return
     */
    public T getById(final Serializable id) {
        return getCommonDao().getById(id);
    }

    public Object getOutCache(String key) throws ServiceException {
        Cache cache = ehcacheManager.getCache(CACHE_NAME);
        if (cache == null)
            return null;

        Element element = cache.get(key);
        if (element == null)
            return null;

        return element.getObjectValue();
    }

    public void putInCache(String key, Object value) throws ServiceException {
        // if(ehcacheManager.cacheExists(CACHE_NAME)){
        Element element = new Element(key, value);
        Cache cache = ehcacheManager.getCache(CACHE_NAME);
        cache.put(element);
        Element e = cache.get(key);
        if (e == null || e.getObjectValue() == null) {
            logger.error("can't put in cache" + key);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List getAllEhcacheKeys(Integer type) {
        if (type == 1) {
            Cache cache = ehcacheManager.getCache(CACHE_NAME);
            return cache.getKeys();
        } else {
            List list = new ArrayList();
            Properties propertie = PropertiesUtils.loadProperties("classpath:ehcache/ehcache_key.properties");
            Enumeration e = propertie.keys();
            while (e.hasMoreElements()) {
                list.add(e.nextElement());
            }
            return list;
        }
    }

    /**
     * get property from ehcache/ehcache_key.properties
     * 
     * @author songlin.li
     * @param key
     * @return
     */
    private String getEhcacheKey(String key) {
        Properties propertie = PropertiesUtils.loadProperties("classpath:ehcache/ehcache_key.properties");
        /*
         * for(Map.Entry<Object,Object> set :propertie.entrySet()){
         * CacheUtil.setCacheMap(set.getKey().toString(),
         * set.getValue().toString()); }
         */
        key = StringUtil.replace(key, " ", "_");
        key = StringUtil.startsWith(key, "ehcache.") ? key : "ehcache." + key;
        return propertie.getProperty(key, key);
    }

    /**
     * (non-Javadoc)
     * 
     * @see com.crown.servicepartner.common.service.CommonService#cleanAllCache()
     */
    public void cleanAllCache() {
        ehcacheManager.clearAll();
    }

    protected abstract CommonDao<T, Serializable> getCommonDao();
}
